"""StringUtils类 - 提供字符串处理相关的实用功能"""

import re
import json
import yaml
from typing import List, Dict, Any, Optional, Union
from datetime import datetime
import html
import urllib.parse
import hashlib
import base64

from rpa_framework.rpa_logging.logger import Logger
from rpa_framework.exceptions.rpa_exceptions import StringProcessingException

class StringUtils:
    """字符串工具类，提供字符串处理、格式化、转换等功能"""
    
    def __init__(self):
        """初始化字符串工具类"""
        self.logger = Logger("StringUtils")
    
    def remove_whitespace(self, text: str) -> str:
        """移除字符串中的所有空白字符
        
        Args:
            text: 输入字符串
            
        Returns:
            移除空白字符后的字符串
        """
        self.logger.debug(f"移除空白字符: {text[:50]}...")
        return ''.join(text.split())
    
    def trim(self, text: str) -> str:
        """去除字符串两端的空白字符
        
        Args:
            text: 输入字符串
            
        Returns:
            去除两端空白后的字符串
        """
        return text.strip()
    
    def to_title_case(self, text: str) -> str:
        """转换为标题格式（每个单词首字母大写）
        
        Args:
            text: 输入字符串
            
        Returns:
            标题格式的字符串
        """
        return text.title()
    
    def to_snake_case(self, text: str) -> str:
        """转换为蛇形命名法（下划线分隔）
        
        Args:
            text: 输入字符串（可以是驼峰式或帕斯卡式）
            
        Returns:
            蛇形命名的字符串
        """
        # 处理驼峰式命名（例如：camelCase -> camel_case）
        s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', text)
        # 处理帕斯卡式命名（例如：PascalCase -> pascal_case）
        snake_case = re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
        # 移除任何非字母数字字符，替换为下划线
        snake_case = re.sub(r'[^a-z0-9_]', '_', snake_case)
        # 移除连续的下划线
        snake_case = re.sub(r'_+', '_', snake_case)
        # 移除开头和结尾的下划线
        return snake_case.strip('_')
    
    def to_camel_case(self, text: str) -> str:
        """转换为驼峰式命名法（第一个单词小写）
        
        Args:
            text: 输入字符串（可以是下划线分隔或空格分隔）
            
        Returns:
            驼峰式命名的字符串
        """
        # 将下划线或空格分隔的字符串转换为驼峰式
        parts = re.split(r'[\s_\-]+', text.lower())
        if not parts:
            return text
        
        # 第一个单词保持小写，其余单词首字母大写
        return parts[0] + ''.join(word.capitalize() for word in parts[1:])
    
    def to_pascal_case(self, text: str) -> str:
        """转换为帕斯卡式命名法（每个单词首字母大写）
        
        Args:
            text: 输入字符串（可以是下划线分隔或空格分隔）
            
        Returns:
            帕斯卡式命名的字符串
        """
        # 将下划线或空格分隔的字符串转换为帕斯卡式
        parts = re.split(r'[\s_\-]+', text.lower())
        if not parts:
            return text
        
        # 每个单词首字母大写
        return ''.join(word.capitalize() for word in parts)
    
    def extract_numbers(self, text: str) -> List[float]:
        """从字符串中提取所有数字
        
        Args:
            text: 输入字符串
            
        Returns:
            提取的数字列表
        """
        numbers = re.findall(r'-?\d+\.?\d*', text)
        return [float(num) for num in numbers]
    
    def extract_emails(self, text: str) -> List[str]:
        """从字符串中提取所有电子邮件地址
        
        Args:
            text: 输入字符串
            
        Returns:
            电子邮件地址列表
        """
        email_pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
        return re.findall(email_pattern, text)
    
    def extract_urls(self, text: str) -> List[str]:
        """从字符串中提取所有URL
        
        Args:
            text: 输入字符串
            
        Returns:
            URL列表
        """
        url_pattern = r'https?://[\w\-._~:/?#[\]@!$&\'()*+,;=]+'
        return re.findall(url_pattern, text)
    
    def format_date(self, date_obj: datetime, format_string: str = "%Y-%m-%d") -> str:
        """格式化日期为字符串
        
        Args:
            date_obj: datetime对象
            format_string: 日期格式字符串
            
        Returns:
            格式化后的日期字符串
        """
        return date_obj.strftime(format_string)
    
    def parse_date(self, date_string: str, format_string: str = "%Y-%m-%d") -> datetime:
        """从字符串解析日期
        
        Args:
            date_string: 日期字符串
            format_string: 日期格式字符串
            
        Returns:
            datetime对象
            
        Raises:
            StringProcessingException: 日期解析失败
        """
        try:
            return datetime.strptime(date_string, format_string)
        except ValueError as e:
            raise StringProcessingException(f"无法解析日期: {str(e)}") from e
    
    def contains_only_digits(self, text: str) -> bool:
        """检查字符串是否只包含数字
        
        Args:
            text: 输入字符串
            
        Returns:
            是否只包含数字
        """
        return text.isdigit()
    
    def contains_only_letters(self, text: str) -> bool:
        """检查字符串是否只包含字母
        
        Args:
            text: 输入字符串
            
        Returns:
            是否只包含字母
        """
        return text.isalpha()
    
    def contains_only_alphanumeric(self, text: str) -> bool:
        """检查字符串是否只包含字母和数字
        
        Args:
            text: 输入字符串
            
        Returns:
            是否只包含字母和数字
        """
        return text.isalnum()
    
    def count_occurrences(self, text: str, substring: str) -> int:
        """计算子字符串在文本中出现的次数
        
        Args:
            text: 原始文本
            substring: 要查找的子字符串
            
        Returns:
            出现次数
        """
        return text.count(substring)
    
    def replace_multiple(self, text: str, replacements: Dict[str, str]) -> str:
        """执行多次字符串替换
        
        Args:
            text: 原始文本
            replacements: 替换字典 {要替换的字符串: 替换为的字符串}
            
        Returns:
            替换后的文本
        """
        result = text
        for old, new in replacements.items():
            result = result.replace(old, new)
        return result
    
    def safe_substring(self, text: str, start: int, end: Optional[int] = None) -> str:
        """安全地截取子字符串（处理超出范围的情况）
        
        Args:
            text: 原始文本
            start: 起始索引
            end: 结束索引
            
        Returns:
            子字符串
        """
        # 确保索引有效
        start = max(0, min(start, len(text)))
        if end is None:
            end = len(text)
        else:
            end = max(0, min(end, len(text)))
        
        return text[start:end]
    
    def truncate(self, text: str, max_length: int, suffix: str = "...") -> str:
        """截断字符串到指定长度
        
        Args:
            text: 原始文本
            max_length: 最大长度
            suffix: 截断后添加的后缀
            
        Returns:
            截断后的字符串
        """
        if len(text) <= max_length:
            return text
        
        # 确保后缀不会导致最终字符串超过最大长度
        if len(suffix) >= max_length:
            return text[:max_length]
        
        return text[:(max_length - len(suffix))] + suffix
    
    def normalize_whitespace(self, text: str) -> str:
        """标准化空白字符（将多个空格、制表符等替换为单个空格）
        
        Args:
            text: 原始文本
            
        Returns:
            标准化后的文本
        """
        return re.sub(r'\s+', ' ', text).strip()
    
    def clean_string(self, text: str) -> str:
        """清理字符串（去除非ASCII字符，保留常见符号）
        
        Args:
            text: 原始文本
            
        Returns:
            清理后的文本
        """
        # 保留字母、数字、空格和常见符号
        return re.sub(r'[^a-zA-Z0-9\s.,!?-]', '', text)
    
    def escape_special_characters(self, text: str) -> str:
        """转义特殊字符
        
        Args:
            text: 原始文本
            
        Returns:
            转义后的文本
        """
        # 转义正则表达式特殊字符
        return re.escape(text)
    
    def unescape_html(self, text: str) -> str:
        """解码HTML转义字符
        
        Args:
            text: 包含HTML转义字符的文本
            
        Returns:
            解码后的文本
        """
        return html.unescape(text)
    
    def escape_html(self, text: str) -> str:
        """编码HTML特殊字符
        
        Args:
            text: 原始文本
            
        Returns:
            编码后的文本
        """
        return html.escape(text)
    
    def url_encode(self, text: str) -> str:
        """URL编码
        
        Args:
            text: 原始文本
            
        Returns:
            URL编码后的文本
        """
        return urllib.parse.quote(text)
    
    def url_decode(self, text: str) -> str:
        """URL解码
        
        Args:
            text: URL编码的文本
            
        Returns:
            解码后的文本
        """
        return urllib.parse.unquote(text)
    
    def generate_hash(self, text: str, algorithm: str = "md5") -> str:
        """生成字符串的哈希值
        
        Args:
            text: 原始文本
            algorithm: 哈希算法（md5, sha1, sha256）
            
        Returns:
            哈希值的十六进制表示
        """
        if algorithm == "md5":
            hash_func = hashlib.md5()
        elif algorithm == "sha1":
            hash_func = hashlib.sha1()
        elif algorithm == "sha256":
            hash_func = hashlib.sha256()
        else:
            raise ValueError(f"不支持的哈希算法: {algorithm}")
        
        hash_func.update(text.encode('utf-8'))
        return hash_func.hexdigest()
    
    def base64_encode(self, text: str) -> str:
        """Base64编码
        
        Args:
            text: 原始文本
            
        Returns:
            Base64编码的字符串
        """
        encoded_bytes = base64.b64encode(text.encode('utf-8'))
        return encoded_bytes.decode('utf-8')
    
    def base64_decode(self, encoded_text: str) -> str:
        """Base64解码
        
        Args:
            encoded_text: Base64编码的文本
            
        Returns:
            解码后的文本
        """
        decoded_bytes = base64.b64decode(encoded_text)
        return decoded_bytes.decode('utf-8')
    
    def validate_email(self, email: str) -> bool:
        """验证电子邮件地址格式
        
        Args:
            email: 要验证的电子邮件地址
            
        Returns:
            格式是否有效
        """
        email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        return bool(re.match(email_pattern, email))
    
    def validate_url(self, url: str) -> bool:
        """验证URL格式
        
        Args:
            url: 要验证的URL
            
        Returns:
            格式是否有效
        """
        url_pattern = r'^https?://[\w\-._~:/?#[\]@!$&\'()*+,;=]+$'
        return bool(re.match(url_pattern, url))
    
    def load_json(self, json_str: str) -> Any:
        """从JSON字符串加载数据
        
        Args:
            json_str: JSON字符串
            
        Returns:
            解析后的数据
            
        Raises:
            StringProcessingException: JSON解析失败
        """
        try:
            return json.loads(json_str)
        except json.JSONDecodeError as e:
            raise StringProcessingException(f"JSON解析失败: {str(e)}") from e
    
    def dump_json(self, data: Any, indent: Optional[int] = None) -> str:
        """将数据转换为JSON字符串
        
        Args:
            data: 要转换的数据
            indent: 缩进空格数
            
        Returns:
            JSON字符串
            
        Raises:
            StringProcessingException: JSON序列化失败
        """
        try:
            return json.dumps(data, ensure_ascii=False, indent=indent)
        except TypeError as e:
            raise StringProcessingException(f"JSON序列化失败: {str(e)}") from e
    
    def load_yaml(self, yaml_str: str) -> Any:
        """从YAML字符串加载数据
        
        Args:
            yaml_str: YAML字符串
            
        Returns:
            解析后的数据
            
        Raises:
            StringProcessingException: YAML解析失败
        """
        try:
            return yaml.safe_load(yaml_str)
        except yaml.YAMLError as e:
            raise StringProcessingException(f"YAML解析失败: {str(e)}") from e
    
    def dump_yaml(self, data: Any) -> str:
        """将数据转换为YAML字符串
        
        Args:
            data: 要转换的数据
            
        Returns:
            YAML字符串
            
        Raises:
            StringProcessingException: YAML序列化失败
        """
        try:
            return yaml.dump(data, default_flow_style=False, allow_unicode=True)
        except Exception as e:
            raise StringProcessingException(f"YAML序列化失败: {str(e)}") from e
    
    def mask_sensitive_info(self, text: str, pattern: str = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', mask: str = "***@***.**") -> str:
        """掩盖敏感信息
        
        Args:
            text: 原始文本
            pattern: 匹配敏感信息的正则表达式模式（默认为电子邮件）
            mask: 替换的掩码
            
        Returns:
            掩盖敏感信息后的文本
        """
        return re.sub(pattern, mask, text)
    
    def split_into_lines(self, text: str) -> List[str]:
        """将文本按行分割
        
        Args:
            text: 原始文本
            
        Returns:
            行列表
        """
        # 处理不同的换行符
        return [line.rstrip('\r') for line in text.splitlines()]
    
    def join_with_lines(self, lines: List[str]) -> str:
        """将行列表连接为文本
        
        Args:
            lines: 行列表
            
        Returns:
            连接后的文本
        """
        return '\n'.join(lines)

if __name__ == "__main__":
    # 示例用法
    string_utils = StringUtils()
    
    # 测试转换功能
    print("=== 测试字符串转换 ===")
    test_str = "hello world thisIsCamelCase And_This_Is_Snake_Case"
    print(f"原始字符串: {test_str}")
    print(f"标题格式: {string_utils.to_title_case(test_str)}")
    print(f"蛇形命名: {string_utils.to_snake_case(test_str)}")
    print(f"驼峰命名: {string_utils.to_camel_case(test_str)}")
    print(f"帕斯卡命名: {string_utils.to_pascal_case(test_str)}")
    
    # 测试提取功能
    print("\n=== 测试提取功能 ===")
    mixed_str = "联系我们: john.doe@example.com 或 visit https://example.com, 电话: 123-456-7890"
    print(f"提取电子邮件: {string_utils.extract_emails(mixed_str)}")
    print(f"提取URL: {string_utils.extract_urls(mixed_str)}")
    print(f"提取数字: {string_utils.extract_numbers(mixed_str)}")
    
    # 测试验证功能
    print("\n=== 测试验证功能 ===")
    test_email = "user@example.com"
    test_url = "https://www.example.com/page"
    print(f"验证电子邮件 '{test_email}': {string_utils.validate_email(test_email)}")
    print(f"验证URL '{test_url}': {string_utils.validate_url(test_url)}")
    
    # 测试编码/解码功能
    print("\n=== 测试编码/解码功能 ===")
    original = "Hello World! 你好，世界！"
    encoded = string_utils.base64_encode(original)
    decoded = string_utils.base64_decode(encoded)
    print(f"原始文本: {original}")
    print(f"Base64编码: {encoded}")
    print(f"Base64解码: {decoded}")
    
    # 测试掩码功能
    print("\n=== 测试掩码功能 ===")
    sensitive_text = "用户ID: 123456, 邮箱: admin@example.com, 手机号: 13800138000"
    masked = string_utils.mask_sensitive_info(sensitive_text)
    print(f"原始文本: {sensitive_text}")
    print(f"掩码后: {masked}")